﻿
// <copyright file="DispatchingHelper.cs" company="Subhadra Software Solutions">
//   
// </copyright>
// <summary>
//   The dispatching helper.
// </summary>


namespace SubhadraSolutions.Sharp.Utils.Threading
{
    using System;
    using System.Collections.Generic;

    /// <summary>
    /// The dispatching helper.
    /// </summary>
    public static class DispatchingHelper
    {
        /// <summary>
        /// Dispatches the specified delegates.
        /// </summary>
        /// <param name="delegates">The delegates.</param>
        /// <param name="dispatcherProvider">The dispatcher provider.</param>
        /// <param name="arguments">The arguments.</param>
        public static void Dispatch(IEnumerable<Delegate> delegates, IDispatcherProvider dispatcherProvider, params object[] arguments)
        {
            Dispatch(delegates, dispatcherProvider, del => del.DynamicInvoke(arguments));
        }

        /// <summary>
        /// Dispatches the specified delegates.
        /// </summary>
        /// <param name="delegates">The delegates.</param>
        /// <param name="dispatcherProvider">The dispatcher provider.</param>
        /// <param name="action">The action.</param>
        public static void Dispatch(IEnumerable<Delegate> delegates, IDispatcherProvider dispatcherProvider, Action<Delegate> action)
        {
            if (dispatcherProvider == null)
            {
                foreach (var del in delegates)
                {
                    del.DynamicInvoke(action);
                }

                return;
            }

            foreach (var del in delegates)
            {
                if (del == null)
                {
                    continue;
                }

                Delegate[] invocationList = del.GetInvocationList();
                if (invocationList.Length > 1)
                {
                    Dispatch(invocationList, dispatcherProvider, action);
                }
                else
                {
                    IDispatcher dispatcher = null;
                    if (del.Target != null)
                    {
                        dispatcher = dispatcherProvider.GetDispatcher(del.Target);
                    }

                    if (dispatcher == null)
                    {
                        action(del);
                    }
                    else
                    {
                        Delegate delegateToBeCalled = del;
                        dispatcher.Dispatch(() => action(delegateToBeCalled));
                    }
                }
            }
        }
    }
}
